/*
 * Copyright:  2018 smarabbit studio.
 *
 *  Licensed under the Confluent Community License; you may not use this file
 *  except in compliance with the License.  You may obtain a copy of the License at
 *
 *  http://www.confluent.io/confluent-community-license
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OF ANY KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations under the License.
 *
 *  @作   者： 黄开晖 (117227773@qq.com)
 *  @日   期:  2021年9月12日
 */
package com.massyframework.beanskin.license.signature.wizard;

import java.io.File;
import java.security.Key;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Optional;

import com.massyframework.beanskin.license.signature.ras.BCRSAKeyReader;

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.FileChooser;

/**
 * 选择证书控制器
 * @author huangkh
 *
 */
public class SelectCertificateionController extends Controller{

	@FXML
	private Button btnNext;
	@FXML
	private Button btnPrevious;

	@FXML
	private Button btnSelect;
	
	@FXML
	private TableView<CertificateEntry> tvKey;
	@FXML
	private TableColumn<CertificateEntry, String> tcAlias;
	@FXML
	private TableColumn<CertificateEntry, String> tcSigAlgName;
	@FXML
	private TableColumn<CertificateEntry, String> tcIssuerDN;
	
	/**
	 * 
	 */
	public SelectCertificateionController() {
	}

	@Override
	protected void init() {
		this.btnNext.setDisable(true);
		
		this.tcAlias.setCellValueFactory(new PropertyValueFactory<CertificateEntry, String>("alias"));
		this.tcSigAlgName.setCellValueFactory(new PropertyValueFactory<CertificateEntry, String>("sigAlgName"));
		this.tcIssuerDN.setCellValueFactory(new PropertyValueFactory<CertificateEntry, String>("issuerDN"));
		
		this.tvKey.getSelectionModel().selectedItemProperty().addListener(
				new ChangeListener<CertificateEntry>() {

					@Override
					public void changed(ObservableValue<? extends CertificateEntry> observable,
							CertificateEntry oldValue, CertificateEntry newValue) {
						btnNext.setDisable(newValue == null);						
					}
				}
				);
	}

	@Override
	public void destroy() {
		
	}

	@FXML
	protected void onSelectClick() {
		FileChooser fileChooser = new FileChooser();
		fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("密钥存储文件", "*.keystore"));
		fileChooser.setTitle("选择存放证书的KeyStore文件");
		File file = fileChooser.showOpenDialog(this.getWizard().getStage());

		if (file != null) {
			Optional<String> password =
					PasswordUtils.openPasswordDialog("输入提示框", "要提取签名的证书，需要keystore的密码", "请输入密码:");			
			password.ifPresent( txt ->{
				List<CertificateEntry> entries = this.listCertificateEntris(file, txt.toCharArray());
				
				ObservableList<CertificateEntry> list = FXCollections.observableArrayList();
				list.addAll(entries);
				this.tvKey.setItems(list);
			});
		}
	}
	
	protected List<CertificateEntry> listCertificateEntris(File file, char[] storePass) {
		
		try {
			List<CertificateEntry> result = new ArrayList<>();
			BCRSAKeyReader reader = new BCRSAKeyReader(); 
			KeyStore keystore = reader.loadKeyStore(file, storePass);
			
			Enumeration<String> em = keystore.aliases();
			while (em.hasMoreElements()) {
				String alias = em.nextElement();				
	
				Certificate[] certs = keystore.getCertificateChain(alias);
				if (certs != null) {
					for (Certificate cert : certs) {
						if ((cert instanceof X509Certificate)) {
							X509Certificate x509cert = (X509Certificate)cert;
							CertificateEntry entry = new CertificateEntry(keystore, alias, 
									x509cert);
							result.add(entry);
						}
					}
				}				
			}
			return result;
			
		}catch(Exception e) {
			Alert alert = new Alert(AlertType.ERROR);
			alert.setTitle("错误");
			alert.setHeaderText("密码错误，无法打开keystore文件。");
			alert.setContentText(e.getMessage());
			alert.showAndWait();
		}
		return new ArrayList<>();
	}
	
	@FXML
	protected void onPreviousClick() {
		this.getWizard().doPrevious();
	}
	
	@FXML
	protected void onNextClick() {
		CertificateEntry entry = this.tvKey.getSelectionModel().getSelectedItem();
		if (entry == null) return;
		
		if (entry.getKey() == null) {
			Optional<String> password =
					PasswordUtils.openPasswordDialog("输入提示框", "需要提取存放在keyStore中的签名私钥，请输入证书密钥", "请输入密码:");
			if (!password.isPresent()) {
				return;
			}
			
			try {
				Key key = entry.getKeyStore().getKey(entry.getAlias(), password.get().toCharArray());
				entry.setKey((PrivateKey)key);
			} catch (Exception e) {
				Alert alert = new Alert(AlertType.ERROR);
				alert.setTitle("错误");
				alert.setHeaderText("读取私钥发生错误");
				alert.setContentText(e.getMessage());
				alert.showAndWait();
				return;
			} 
		}
		
		this.getWizard().getSignatureData().setCertificateEntry(entry);
		this.getWizard().doNext();
	}
}
